<?php

/**
 * Framework_DB_DaoCollection
 *
 * A collection class to hold multiple DaoNode objects
 *
 * @author Application Support Group
 * @copyright University of Georgia
 * @package BAMF
 * @see Framework_DB
 * @filesource
*/


#abstract class Framework_DB_DaoCollection extends Framework_DB {
class Framework_DB_DaoCollection extends Framework_DB implements IteratorAggregate {

	protected $_DB_TABLE ;		# the database table
	protected $_PK_FIELD ;		# the primary key field
	public $_nodeClassName ;	# the type of DaoNode to store in the collection
	public $_parameters ;		# Parameters for creating the collection
	public $_schema ;			# the schema definition
	public $_data ;				# the array of DaoNode objects
	public $_pager ;			# the CollectionPager
	public $_size ;				# the number of DaoNodes

	/**
	* Constructor
	*/
	public function __construct( $aClassName, $aParameterSet=null, $aPager=null ) {

		$this->_nodeClassName = $aClassName ;
		$theSchemaFile = eval( "return $aClassName::getSchemaFile();" ) ;

		if( file_exists( $theSchemaFile )) {
			$this->_schema = parse_ini_file( $theSchemaFile, true ) ; 
		} else {
			$this->_schema = Framework_ErrorHandler::raiseError( "No database schema file found for class: Tried '{$theSchemaFile}'", __METHOD__."::".__LINE__ ) ;
		}
		
		if( Framework_ErrorHandler::isError( $this->_schema, '', false )) {
			die( $this->_schema->getMessage() ) ;
		} else {
					
			if ( isset( $this->_schema['db_parameters']['schema'] )) {
				$this->_DB_TABLE = $this->_schema['db_parameters']['schema'] . '.' . $this->_schema['db_parameters']['table'] ;
			} else {
				$this->_DB_TABLE .= $this->_schema['db_parameters']['table'] ;
			}


			if ( isset( $this->_schema['db_parameters']['dsn'] )) {
				$theDsn = $this->_schema['db_parameters']['dsn'] ;
			} else {
				$theDsn = FRAMEWORK_DSN ;
			}

			$this->_PK_FIELD = $this->_schema['db_parameters']['pkfield'] ;
		}

		// make sure we have a valid parameters object
		$this->_parameters = new Framework_DB_DaoParameters() ;
		if( $aParameterSet instanceof Framework_DB_DaoParameters ) {
			$this->_parameters = $aParameterSet ;
		}
		// make sure 'sortvar' is set and valid
		$sv = $this->_parameters->sortvar ;
		if( empty( $sv ) || 
			!in_array( $sv, $this->_schema['fields']) || 
			$this->_schema['field_definitions'][$sv] == DB_DATATYPE_VIRTUAL) {
			
			$this->_parameters->sortvar = $this->_schema['db_parameters']['default_sortvar'] ;
		}

		// make sure 'sortdir' is set and valid
		$sd = $this->_parameters->sortdir ;
		if( empty( $sd ) || !in_array( $sd, array( "ASC", "DESC" ))) {
			$this->_parameters->sortdir = $this->_schema['db_parameters']['default_sortdir'] ;
		}

		$fs = $this->_parameters->fields ;

		if ( !is_array( $fs ) || count( $fs ) == 0 ) {
			$this->_parameters->fields = $this->_schema['fields'] ;
		}


		// make sure we have a valid pager
		$this->_pager = new Framework_DB_DaoCollectionPager() ;
		if( $aPager instanceof Framework_DB_DaoCollectionPager ) {
			$this->_pager = $aPager ;
		}

		parent::__construct( $theDsn ) ;

		// create the collection
		$this->_data = array() ;
		$this->_size = 0 ;
		$this->_data = $this->getCollection() ;

		if( Framework_ErrorHandler::isError( $this->_data, __METHOD__."::".__LINE__ )) {
			if( SHOW_DEBUG ) {
				Framework_Util_Debug::show( array( __METHOD__, "{$this->_nodeClassName}::{$this->_data->toString()}" )) ;
			} else {
				Framework_Util_Debug::show( array( __METHOD__, "Error instantiating class ".__CLASS__ )) ;
			}
		} else {
			$this->_size = count( $this->_data ) ;
		}


	}// end constructor



	/**
	 * getCollection
	 *
	 * Helper method for the constructor.  Instantiates the Node collection.
	 *
	 * @return array Array of DaoNode objects on success. Return PEAR_Error on failure.
	*/
	protected function getCollection() {

		switch( $this->db->dsn['dbsyntax'] ) {
		case DSN_OCI :
			return $this->getOciCollection() ;
			break;

		case DSN_MSSQL :
			return $this->getMssqlCollection() ;
			break;

		case DSN_MYSQL :
			return $this->getMysqlCollection() ;
			break;

		default :
			return Framework_ErrorHandler::raiseError( "No DSN defined.", __METHOD__."::".__LINE__ ) ;
			break;

		}// end switch

	}// end getCollection()



	/**
	 * getOciCollection
	 *
	 * Helper method for the constructor.  Instantiates the Node collection.
	*/
	private function getOciCollection() {

		$_output = array() ;
		$whereFragment = $this->_parameters->where ;
		$fieldsA = "" ;
		$fieldsB = "" ;
		$fieldCount = count( $this->_parameters->fields ) ;

		for( $i=0; $i<$fieldCount; $i++ ) {
			//$field = $this->_schema['fields'][$i] ;
			$field = $this->_parameters->fields[$i] ;
			if( $this->_schema['field_definitions'][$field] == DB_DATATYPE_VIRTUAL ) {
				continue ;
			}
				
			if( $fieldsA != '') {
				$fieldsA .= ", " ;
				$fieldsB .= ", " ;
			}

			if( $this->_schema['field_definitions'][$field] == DB_DATATYPE_DATETIME ) {
				$fieldsA .= "TO_CHAR( $field, '".OCI_DATE_FORMAT_STRING."' ) AS $field" ;
				$fieldsB .= "$field" ;
			} else {
				$fieldsA .= $field ;
				$fieldsB .= $field ;
			}

		}

		$countSql = "SELECT COUNT( {$this->_PK_FIELD} ) AS " . KEYWORD_SQL_COUNT . " FROM {$this->_DB_TABLE} $whereFragment" ;
		$preparedCount = $this->db->prepare($countSql) ;

		if(Framework_ErrorHandler::isError($preparedCount)) {
			return $preparedCount;
		}

		$countResult = $preparedCount->execute( $this->_parameters->values ) ;

		$preparedCount->free();

		if( Framework_ErrorHandler::isError( $countResult, __METHOD__."::".__LINE__ )) {
			$_output = $countResult ;
		} else {
			// determine limit/pager info

			$countResult = $countResult->fetchRow();

			$recordCount = $countResult[KEYWORD_SQL_COUNT] ;
			$this->_pager->totalrecs = $recordCount ;
			$this->_pager->pagecount = @ceil($this->_pager->totalrecs / $this->_pager->limit) ;

			$sql = "SELECT * FROM
					(SELECT ROWNUM RN, $fieldsA FROM
						(SELECT $fieldsB 
						FROM {$this->_DB_TABLE}
						$whereFragment
						ORDER BY {$this->_parameters->sortvar} {$this->_parameters->sortdir})
					)
				WHERE RN > {$this->_pager->offset}
				AND RN <= " . ($this->_pager->offset + $this->_pager->limit)
				;


			$preparedStmt = $this->db->prepare($sql);
			if(Framework_ErrorHandler::isError($preparedStmt)) {
				return $preparedStmt;
			}

			$result = $preparedStmt->execute($this->_parameters->values) ;
			$preparedStmt->free();

			
			if( Framework_ErrorHandler::isError( $result, __METHOD__."::".__LINE__ )) {
				$_output = $result ;
			} else {

				while( $nextRec = $result->fetchRow( MDB2_FETCHMODE_ASSOC )) {
					if( Framework_ErrorHandler::isError( $nextRec, __METHOD__."::".__LINE__ )) {
						$_output = $nextRec ;
						break ;
					} else {
						$recordId = $nextRec[$this->_PK_FIELD] ;
						$nextItem = new $this->_nodeClassName( $recordId, false ) ;

						foreach( $this->_parameters->fields as $field ) {
							if( $this->_schema['field_definitions'][$field] == DB_DATATYPE_VIRTUAL ) {
								continue ;
							}
							$nextItem->$field = $nextRec[$field];
						}

						$_output[] = $nextItem ;
					}
				}

				$result->free() ;
			}
		}

		return $_output ;

	}// end getOciCollection()



	/**
	 * getMssqlCollection
	 *
	 * Helper method for the constructor.  Instantiates the Node collection.
	*/
	private function getMssqlCollection() {

		$_output = array() ;
		$whereFragment = $this->_parameters->where ;
		$fields = "" ;
		$revSort = array( "ASC" => "DESC", "DESC" => "ASC" ) ;

		$fieldCount = count( $this->_parameters->fields ) ;

		for( $i=0; $i<$fieldCount; $i++ ) {
			$field = $this->_parameters->fields[$i] ;
			if( $this->_schema['field_definitions'][$field] == DB_DATATYPE_VIRTUAL ) {
				continue ;
			}
			if( $fields != '' ) {
				$fields .= "," ;
			}
			$fields .= $field ;
		}

		$countSql = "SELECT COUNT( {$this->_PK_FIELD} ) AS " . KEYWORD_SQL_COUNT . " FROM {$this->_DB_TABLE} $whereFragment" ;
		$preparedCount = $this->db->prepare($countSql) ;

		if(Framework_ErrorHandler::isError($preparedCount)) {
			return $preparedCount;
		}

		$countResult = $preparedCount->execute( $this->_parameters->values ) ;

		$preparedCount->free();

		if( Framework_ErrorHandler::isError( $countResult, __METHOD__."::".__LINE__ )) {
			$_output = $countResult ;
		} else {
			// determine limit/pager info

			$countResult = $countResult->fetchRow();
			$recordCount = $countResult[KEYWORD_SQL_COUNT] ;
			$this->_pager->totalrecs = $recordCount ;
			$this->_pager->pagecount = @ceil($this->_pager->totalrecs / $this->_pager->limit) ;

			$upperBound = $this->_pager->offset + $this->_pager->limit ;
			
			$limit = min($this->_pager->limit, max(0, $this->_pager->totalrecs - $this->_pager->offset));

			// make sure we don't try to sort on the same field twice
			if ( $this->_parameters->sortvar == $this->_PK_FIELD ) {
				$sql = "
					SELECT $fields FROM (
						SELECT TOP {$limit} $fields from (
							SELECT TOP $upperBound $fields from {$this->_DB_TABLE} $whereFragment
							ORDER BY {$this->_parameters->sortvar} {$this->_parameters->sortdir}
						) AS foo
						ORDER BY {$this->_parameters->sortvar} " . $revSort[ $this->_parameters->sortdir ] . 
					") AS bar
					ORDER BY {$this->_parameters->sortvar} {$this->_parameters->sortdir}
				" ;
			
			} else {
				$sql = "
					SELECT $fields FROM (
						SELECT TOP {$limit} $fields from (
							SELECT TOP $upperBound $fields from {$this->_DB_TABLE} $whereFragment
							ORDER BY {$this->_parameters->sortvar} {$this->_parameters->sortdir}, {$this->_PK_FIELD} {$this->_parameters->sortdir}
						) AS foo
						ORDER BY {$this->_parameters->sortvar} " . $revSort[ $this->_parameters->sortdir ] . ", {$this->_PK_FIELD} " . $revSort[ $this->_parameters->sortdir ] .
					") AS bar
					ORDER BY {$this->_parameters->sortvar} {$this->_parameters->sortdir}, {$this->_PK_FIELD} {$this->_parameters->sortdir}
				" ;
			
			}

			$preparedStmt = $this->db->prepare($sql);

			if(Framework_ErrorHandler::isError($preparedStmt)) {
				return $preparedStmt;
			}

			$result = $preparedStmt->execute($this->_parameters->values) ;

			$preparedStmt->free();

			if( Framework_ErrorHandler::isError( $result, __METHOD__."::".__LINE__ )) {
				$_output = $result ;
			} else {

				while( $nextRec = $result->fetchRow( MDB2_FETCHMODE_ASSOC )) {
					if( Framework_ErrorHandler::isError( $nextRec, __METHOD__."::".__LINE__ )) {
						$_output = $nextRec ;
						break ;
					} else {
						$recordId = $nextRec[$this->_PK_FIELD] ;
						$nextItem = new $this->_nodeClassName( $recordId, false ) ;

						foreach( $this->_parameters->fields as $field ) {
							if( $this->_schema['field_definitions'][$field] == DB_DATATYPE_VIRTUAL ) {
								continue ;
							}
							$nextItem->$field = $nextRec[$field];
						}

						$_output[] = $nextItem ;
					}
				}

				$result->free() ;
			}

		}
		return $_output ;

	}// end getMssqlCollection()



	/**
	 * getMysqlCollection
	 *
	 * Helper method for the constructor.  Instantiates the Node collection.
	*/
	private function getMysqlCollection() {

		$_output = array() ;
		$whereFragment = $this->_parameters->where ;
		$fields = "" ;
		$fieldCount = count( $this->_parameters->fields ) ;

		for( $i=0; $i<$fieldCount; $i++ ) {
			//$field = $this->_schema['fields'][$i] ;
			$field = $this->_parameters->fields[$i] ;
			if( $this->_schema['field_definitions'][$field] == DB_DATATYPE_VIRTUAL ) {
				continue ;
			}
			if($fields != '') {
				$fields .= "," ;
			}
			$fields .= $field ;
		}

		$countSql = "SELECT COUNT( {$this->_PK_FIELD} ) AS " . KEYWORD_SQL_COUNT . " FROM {$this->_DB_TABLE} $whereFragment" ;
		$sql = "SELECT $fields FROM {$this->_DB_TABLE}" . $whereFragment . "ORDER BY {$this->_parameters->sortvar} {$this->_parameters->sortdir}" ;

		$preparedCount = $this->db->prepare($countSql) ;

		if(Framework_ErrorHandler::isError($preparedCount)) {
			return $preparedCount;
		}

		$countResult = $preparedCount->execute( $this->_parameters->values ) ;

		$preparedCount->free();

		

		if( Framework_ErrorHandler::isError( $countResult, __METHOD__."::".__LINE__ )) {
			$_output = $countResult ;
		} else {
			// determine limit/pager info

			$countResult = $countResult->fetchRow();
			$recordCount = $countResult[KEYWORD_SQL_COUNT] ;
			$this->_pager->totalrecs = $recordCount ;
			$this->_pager->pagecount = @ceil($this->_pager->totalrecs / $this->_pager->limit) ;


			$preparedStmt = $this->db->prepare($sql);

			if(Framework_ErrorHandler::isError($preparedStmt)) {
				return $preparedStmt;
			}
			$result = $preparedStmt->execute($this->_parameters->values) ;

			$preparedStmt->free();

			if( Framework_ErrorHandler::isError( $result, __METHOD__."::".__LINE__ )) {
				$_output = $result ;
			} else {

				for( $i=$this->_pager->offset; $i<($this->_pager->offset+$this->_pager->limit); $i++ ) {
					if( $i < $recordCount ) {
						$nextRec = $result->fetchRow( MDB2_FETCHMODE_ASSOC, $i ) ;

						if( Framework_ErrorHandler::isError( $nextRec, __METHOD__."::".__LINE__ )) {
							$_output = $nextRec ;
							break ;
						} else {
							$nextItem = new $this->_nodeClassName( $nextRec[$this->_PK_FIELD], false ) ;

							foreach( $this->_parameters->fields as $field ) {
								if( $this->_schema['field_definitions'][$field] == DB_DATATYPE_VIRTUAL ) {
									continue ;
								}
								$nextItem->$field = $nextRec[$field];
							}

							$_output[] = $nextItem ;
						}
					}
				}

				$result->free() ;
			}

		}
		return $_output ;

	}// end getMysqlCollection()




	/**
	* getParameters
	*
	* Return parameters object for the collection.
	*
	* @return Framework_DB_DaoParameters object
	*
	*/
	public function getParameters() {
		return $this->_parameters ;
	}
	


	/**
	* refresh
	*
	* Re-populate the Collection's data objects from fresh database queries
	*
	*/
	public function refresh() {

		foreach ($this as $thisNode) {
			$result = $thisNode->refresh() ;
			if (Framework_ErrorHandler::isError( $result) ) {
				if( SHOW_DEBUG ) {
					Framework_Util_Debug::show( array( __METHOD__, "{$this->_nodeClassName}::{$result->getMessage()}" )) ;
				}
			}
		}

	}



	/**
	* getByProperty
	*
	* Return a subset of the collection
	*
	* @param $propertyName	The name of the attribute (field name) to search
	* @param $value		The value for which to search
	*
	* @return	array An array of Framework_DB_DaoNode objects.
	*/
	public function getByProperty( $propertyName, $value ) {

		$_output = array() ;

		for( $i=0; $i<$this->_size; $i++ ) {
			$nextObject = $this->_data[$i] ;

			if( $nextObject->$propertyName == $value ) {
				$_output[] = $nextObject ;
			}
		}

		/*
		* not sure whether to do this
		if( empty( $_output )) { $_output = false ; }
		*/
		return $_output ;

	}// end getByProperty




	/**
	* getByUniqueProperty
	*
	* Return an object of the current type if the indicatated property/value is unique
	*
	* @param $propertyName	The name of the attribute (field name) to search
	* @param $value		The value for which to search
	* @param $strict	Whether to return an error if zero or more than one records match.  Defaults to false.
	*
	* @return	mixed Framework_DB_DaoNode object on success; false or PEAR_Error object on failure, depending on the value of $strict
	* @deprecated	Use Framework_DB_DaoNodeFactory.
	*/
	public function getByUniqueProperty( $propertyName, $value, $strict=false ) {

		$_output = false ;

		$subset = $this->getByProperty( $propertyName, $value ) ;

		if( count( $subset ) == 1 ) {
			$_output = $subset[0] ;
		} else {
			if( $strict ) {
				if( count( $subset ) > 1 ) {
					$_output = Framework_ErrorHandler::raiseError( "Multiple objects with requested property found.", __METHOD__."::".__LINE__ ) ;
				} else {
					$_output = Framework_ErrorHandler::raiseError( "No object with requested property found.", __METHOD__."::".__LINE__ ) ;
				}
			}
		}

		return $_output ;
	}





	/**
	* getLookupArray
	*
	* Return an array of lookup values relevant to the primary or another specified key
	*
	* @param $fieldName	The column/field to reference as the lookup values
	* @param $aKeyField	The column to use as the source of index values; defaults to the Collection's primary key field.
	*
	* @return	array	An array of lookup values which will have index values corresponding to the record's primary key value.
	*/
	public function getLookupArray( $fieldName, $aKeyField=null ) {
		$lookupArray = array() ;
		$theKeyField = $this->_PK_FIELD ;

		if( !empty( $aKeyField ) && in_array( $aKeyField, $this->_schema['fields'] )) {
			$theKeyField = $aKeyField ;
		}

		for( $i=0; $i<$this->_size; $i++ ) {
			$nextObj = $this->_data[$i] ;
			$nextId = $nextObj->{$theKeyField} ;
			$nextValue = $nextObj->{$fieldName} ;
			$lookupArray[$nextId] = $nextValue ;
		}

		return $lookupArray;
	}




	/**
	* getCombinedLookupArray
	*
	* Return an array of lookup values by combining the values of mutiple columns
	*
	* @param $nodeType	The type of Framework_DB_DaoNode object on which to base the lookup.
	* @param $fields	An array of fields, the values of which will be concatenated in the return array.
	* @param $delim		The delimeter to use for value concatenation; defaults to comma (",").
	* @param $errors	An array to populate with error messages.
	*
	* @return	array	An array of lookup values which will have index values corresponding to the record's primary key value.
	*/
	public function getCombinedLookupArray( $fields=array(), $delim=',' ) {
		$lookupArray = array() ;
		$theKeyField = $this->_PK_FIELD ;
		$luArrays = array() ;
		$recordIds = array() ;

		if( !empty( $aKeyField ) && in_array( $aKeyField, $this->_schema['fields'] )) {
			$theKeyField = $aKeyField ;
		}

		for( $i=0; $i<count($fields); $i++ ) {
			$nextField = $fields[$i] ;
			$luArrays[] = $this->getLookupArray($nextField) ;
		}

		for( $i=0; $i<count($luArrays); $i++ ) {
			$nextLu = $luArrays[$i] ;
			$recordIds = array_keys( $nextLu ) ;
			break ;
		}

		for( $i=0; $i<count($recordIds); $i++ ) {
			$lookupArray[$recordIds[$i]] = '' ;
		}

		for( $i=0; $i<count($luArrays); $i++ ) {
			$nextLu = $luArrays[$i] ;

			for( $j=0; $j<count($recordIds); $j++ ) {
				$nextId = $recordIds[$j] ;
				$nextVal = $nextLu[$nextId] ;

				if( $i==0 ) {
					$lookupArray[$nextId] = $nextVal ;
				} else {
					$lookupArray[$nextId] .= $delim . $nextVal ;
				}
			}
		}

		return $lookupArray;

	}// end getCombinedLookupArray()




	/**
	* columnToArray
	*
	* Return a column as an array
	*
	* @param $aFieldName	The name of the field whose values should be returned
	*
	* @return	array	The array of values from the indicated column.
	*/
	public function columnToArray( $aFieldName ) {
		$_output = array() ;
		$theField = $this->_PK_FIELD ;

		if( !empty( $aFieldName ) && in_array( $aFieldName, $this->_schema['fields'] )) {
			$theField = $aFieldName ;
		}

		for( $i=0; $i<$this->_size; $i++ ) {
			$nextObj = $this->_data[$i] ;
			$_output[] = $nextObj->{$theField} ;
		}

		return $_output ;
	}




	/**
	* staticGetLookup
	*
	* A means of getting an array of lookup values from a static context.
	*
	* @param $nodeType	The type of Framework_DB_DaoNode object on which to base the lookup.
	* @param $theField	The column/field to reference as the lookup values
	* @param $errors	An array to populate with error messages.
	*
	* @return	array	An array of lookup values which will have index values corresponding to the record's primary key value.
	*/
	public static function staticGetLookup($nodeType, $theField, &$errors) {

		$lookupArray = array();
		$theCollection = Framework_DB_DaoCollectionFactory::build( $nodeType, null, Framework_DB_DaoCollectionPager::getMaxPager() ) ;

		if( !Framework_ErrorHandler::isError( $theCollection )) {
			$lookupArray = $theCollection->getLookupArray($theField);
		} else {
			if( SHOW_DEBUG ) {
				$errors[] = $theCollection->getMessage() ;
				$errors[] = $theCollection->getDebugInfo() ;
			}
		}

		return $lookupArray ;
	}



   /**
    * staticGetParameterizedLookup
    *
    * A means of getting an array of lookup values from a static context that is limited by a WHERE clause.
    *
    * @param $nodeType      The type of Framework_DB_DaoNode object on which to base the lookup.
    * @param $theField      The column/field to reference as the lookup values
	* @param $params		The limiting Framework_Dao_parameters object
    * @param $errors        An array to populate with error messages.
    *
    * @return       array   An array of lookup values which will have index values corresponding to the record's primary key value.
    */
    public static function staticGetParameterizedLookup($nodeType, $theField, $params, &$errors) {

		$lookupArray = array();
		$theCollection = Framework_DB_DaoCollectionFactory::build( $nodeType, $params, Framework_DB_DaoCollectionPager::getMaxPager() ) ;
		
		if( !Framework_ErrorHandler::isError( $theCollection )) {
			$lookupArray = $theCollection->getLookupArray($theField);
		} else {
			if( SHOW_DEBUG ) {
				$errors[] = $theCollection->getMessage() ;
				$errors[] = $theCollection->getDebugInfo() ;
			}
		}
		
		return $lookupArray ;
    }



	/**
	* staticGetCombinedLookup
	*
	* A means of getting an array of lookup values from a static context.
	*
	* @param $nodeType	The type of Framework_DB_DaoNode object on which to base the lookup.
	* @param $fields	An array of fields, the values of which will be concatenated in the return array.
	* @param $delim		The delimeter to use for value concatenation; defaults to comma (",").
	* @param $errors	An array to populate with error messages.
	*
	* @return	array	An array of lookup values which will have index values corresponding to the record's primary key value.
	*/
	public static function staticGetCombinedLookup( $nodeType, $fields=array(), $delim=",", &$errors ) {
		$lookupArray = array() ;
		$luArrays = array() ;
		$recordIds = array() ;

		for( $i=0; $i<count($fields); $i++ ) {
			$nextField = $fields[$i] ;
			$luArrays[] = Framework_DB_DaoCollection::staticGetLookup( $nodeType, $nextField, $errors ) ;
		}

		for( $i=0; $i<count($luArrays); $i++ ) {
			$nextLu = $luArrays[$i] ;
			$recordIds = array_keys( $nextLu ) ;
			break ;
		}

		for( $i=0; $i<count($recordIds); $i++ ) {
			$lookupArray[$recordIds[$i]] = '' ;
		}

		for( $i=0; $i<count($luArrays); $i++ ) {
			$nextLu = $luArrays[$i] ;

			for( $j=0; $j<count($recordIds); $j++ ) {
				$nextId = $recordIds[$j] ;
				$nextVal = $nextLu[$nextId] ;

				if( $i==0 ) {
					$lookupArray[$nextId] = $nextVal ;
				} else {
					$lookupArray[$nextId] .= $delim . $nextVal ;
				}
			}
		}

		return $lookupArray ;

	}// end staticGetCombinedLookup




	/**
	* toXml
	*
	* Return an XML representation of the Collection's data
	*
	* @param $returnFragment	Whether to include the xml version declaration; defaults to false.
	*
	* @return	string	The XML representing the Collection's data.
	*/
	public function toXml( $returnFragment=false, $encoding="ISO-8859-1" ) {

		$_output = "" ;

		if( !$returnFragment ) {
			$_output = "<?xml version='1.0' encoding='$encoding'?>" ;
		}

		$_output .= "<" . get_class( $this ) . ">" ;

		for( $i=0; $i<$this->_size; $i++ ) {
			$nextNode = $this->_data[$i] ;
			$_output .= $nextNode->toXml( true, $encoding ) ;
		}

		$_output .= "</" . get_class( $this ) . ">" ;
		return $_output ;
	}



	public function __toString() {

		$_output = "" ;

		foreach( $this as $nextNode ) {
			$_output .= $nextNode->__toString() ;
		}

		return $_output ;
	}



	/**
	* Desctructor
	*/
	public function __destruct() {
		parent::__destruct() ;
	}

	

	/**
	 * Required by IteratorAggregate interface (for foreaching)
	 */

	public function getIterator() {
		return new ArrayIterator($this->_data);
	}
}

?>
